using System.IO;
using System.Text;
using NFreeMarker.Template;

namespace NFreeMarker.Core
{
    /**
     * An instruction that gets another template
     * and processes it within the current template.
     */

    public sealed class LibraryLoad : TemplateElement
    {
        private readonly Expression _templateName;
        private readonly string _namespace;
        private readonly string _templatePath;

        /**
         * @param template the template that this <tt>Include</tt> is a part of.
         * @param templateName the name of the template to be included.
         * @param namespace the namespace to assign this library to
         */

        internal LibraryLoad(
            Template.Template template,
            Expression templateName,
            string ns)
        {
            _namespace = ns;
            string templatePath1 = template.GetName();
            int lastSlash = templatePath1.LastIndexOf('/');
            _templatePath = lastSlash == -1 ? "" : templatePath1.Substring(0, lastSlash + 1);
            _templateName = templateName;
        }

        internal override void Accept(Environment env)
        {
            string templateNameString = _templateName.GetStringValue(env);
            if (templateNameString == null)
            {
                string msg = "Error " + GetStartLocation()
                             + "The expression " + _templateName + " is undefined.";
                throw new InvalidReferenceException(msg, env);
            }
            Template.Template importedTemplate;
            try
            {
                if (!env.IsClassicCompatible())
                {
                    if (templateNameString.IndexOf("://") > 0)
                    {
                        ;
                    }
                    else if (templateNameString.Length > 0 && templateNameString[0] == '/')
                    {
                        int protIndex = _templatePath.IndexOf("://");
                        if (protIndex > 0)
                        {
                            templateNameString = _templatePath.Substring(0, protIndex + 2) + templateNameString;
                        }
                        else
                        {
                            templateNameString = templateNameString.Substring(1);
                        }
                    }
                    else
                    {
                        templateNameString = _templatePath + templateNameString;
                    }
                }
                importedTemplate = env.GetTemplateForImporting(templateNameString);
            }
            catch (ParseException pe)
            {
                string msg = "Error parsing imported template "
                             + templateNameString;
                throw new TemplateException(msg, pe, env);
            }
            catch (IOException ioe)
            {
                string msg = "Error reading imported file "
                             + templateNameString;
                throw new TemplateException(msg, ioe, env);
            }
            env.ImportLib(importedTemplate, _namespace);
        }

        public override string GetCanonicalForm()
        {
            var buf = new StringBuilder("<#import ");
            buf.Append(_templateName);
            buf.Append(" as ");
            buf.Append(_namespace);
            buf.Append("/>");
            return buf.ToString();
        }

        public override string GetDescription()
        {
            return "import " + _templateName + " as " + _namespace;
        }

        public string GetTemplateName()
        {
            return _templateName.ToString();
        }
    }
}